<?php
class Model_ZendDb_UserService implements Model_UserService
{
	/**
	 * @var Zend_Db_Adapter_Abstract
	 */
	private $_db;
	
	/**
	 * @var Model_ZendDb_DbTable_User
	 */
	private $_user;
	
	/**
	 * @var Model_ZendDb_DbTable_UserProfile
	 */
	private $_profile;
	
	/**
	 * @var Model_ZendDb_DbTable_UserRoles
	 */
	private $_user_roles;
	
	public function __construct()
	{
		$this->_user = new Model_ZendDb_DbTable_User();
		$this->_profile = new Model_ZendDb_DbTable_UserProfile();
		$this->_user_roles = new Model_ZendDb_DbTable_UserRoles();
		
		$this->_db = $this->_user->getAdapter();
	}
	
    /**
     * Save a User entry
     * 
     * @see application/models/Model_UserService#save($user)
     * @param  Default_Model_Entity_User $user
     * @return void
     * @throws Exception
     */
	public function save(Model_Entity_User $user)
    {
        //Recupero i dati dell'utente e del profilo sottoforma di array
        $userData = $user->getOptions();
        $profileData = $user->getUserProfile()->getOptions();
        
        //Rimuovo le proprietà non mappate sulla tabella utente e rimuovo l'oid
        unset($userData['oid']);
        unset($userData['userProfile']);
        unset($userData['ownedCategories']);
        unset($userData['createdCategories']);
        unset($userData['categoriesOfInterest']);
        unset($userData['ownedFeeds']);
        unset($userData['createdFeeds']);
        unset($userData['roles']);
        unset($userData['news']);

        unset($profileData['oid']);
        
        if (empty($userData['password'])) {
        	$userData['password'] = 'none';
        }
        
        try {
        	$this->_db->beginTransaction();
        	
	        $profileID = $this->_profile->insert($profileData);
	        
	        $userData = array_merge($userData, array('profile_oid' => $profileID));
	        $userID = $this->_user->insert($userData);
	            
	        // Inserisco i ruoli dell'utente
	        foreach($user->getRoles() as $role) {
	            $this->_user_roles->insert(array(
	               'user_oid' => $userID,
	               'role_oid' => $role->getOid()
	            ));
	        }
	        
	        $this->_db->commit();
        } catch (Exception $e) {
        	$this->_db->rollBack();
        	
        	throw $e;
        }
    }

    /**
     * Find a user entry by id
     * 
     * @see application/models/Model_UserService#find($userID)
     * @param  int $userID 
     * @return Default_Model_Entity_User
     * @throws Exception
     */
    public function find($userID)
    {
        $result = $this->_user->find($userID);
        $user = null;
        
        if (! 0 == count($result)) {
            $user = new Model_Entity_User($result->current()->toArray());
        }
        
        return $user;
    }

    /**
     * Find user information by it's Username
     * 
     * @param String $username
     * @return Model_Entity_User
     * @throws Exception
     * @see application/models/Model_UserService#findByUsername($username)
     */
    public function findByUsername($username)
    {
        //$select = $this->_user->select()->where('username = ?', $username);
        $select = $this->_db->quoteInto('username = ?', $username);
        $result = $this->_user->fetchRow($select);
        
        $user = null;
        
        if (! 0 == count($result)) {
        	$user = new Model_Entity_User($result->toArray());
        }
        
        return $user;
    }
    
    //TODO RIMUOVERE pare che non è necessario!
    /**
     * Fetch all user entries
     * 
     * @see application/models/Model_UserService#fetchAll()
     * @return array of Model_Entity_User
     * @throws Exception
     */
    /*public function fetchAll()
    {
        $resultSet = $this->_user->fetchAll();
        $entries   = array();
        foreach ($resultSet as $row) {
            $entry = new Model_Entity_User($row->toArray());
            
            $profileRow = $row->findParentRow('Model_ZendDb_DbTable_UserProfile');
            $profile = new Model_Entity_UserProfile($profileRow->toArray());
            $entry->setUserProfile($profile);
            
            $roles = array();
            $rolesRowset = $row->findManyToManyRowset(
                'Model_ZendDb_DbTable_Role', 
                'Model_ZendDb_DbTable_UserRoles');
            foreach ($rolesRowset as $roleRow) {
            	$role = new Model_Entity_Role($roleRow->toArray());
            	$roles[] = $role;
            }
            $entry->setRoles($roles);

            $entries[] = $entry;
        }
        return $entries;
    }*/
    
    /**
     * Search for users matching search criteria based on fullname and nickname
     * contents
     * If no criteria are specified it will return the entire list of feeds
     * in the system
     * 
     * @param array $criteria an optional associative array 
     * @return Zend_Paginator_Adapter_Interface
     * @see application/models/Model_UserService#searchUsers($criteria)
     */
	public function searchUsers($criteria = null)
	{
		$select = $this->_db->select();
        $select->from('user')
               ->join(array('ur' => 'user_roles'),
                            'ur.user_oid = user.oid', null)
               ->join(array('up' => 'userprofile'),
                            'up.oid = user.profile_oid', null)
               ->where('ur.role_oid = "1"');

        if ($criteria !== null) {
            if (isset($criteria['isOpenID'])&& 
                is_numeric($criteria['isOpenID'])) {
                	
                $select->where('user.isOpenID = ?', $criteria['isOpenID']);
            }
            if (isset($criteria['isEnabled']) && 
                is_numeric($criteria['isEnabled'])) {
                	
                $select->where('user.isEnabled = ?', $criteria['isEnabled']);
            }
            if (isset($criteria['contains']) && !empty($criteria['contains'])) {
                $contains = '%'.$criteria['contains'].'%';
                
                $select->where("UPPER(up.nickname) like UPPER('$contains') or ".
                               "UPPER(up.fullname) like UPPER('$contains') or ".
                               "UPPER(user.username) like UPPER('$contains')");
            }
        }
        //die($select->__toString());
        
        return new Model_ZendDb_Paginator_SearchUser($select);
	}

    /**
     * Edit user entry
     * 
     * @see application/models/Model_UserService#edit($user)
	 * @param Model_Entity_User $user
	 * @return void
	 * @throws Exception
	 */
	public function edit(Model_Entity_User $user) {
		$userData = $user->getOptions();
        $profile = $user->getUserProfile();
        
        unset($userData['username']);
        unset($userData['registerDate']);
        unset($userData['userProfile']);
        unset($userData['ownedCategories']);
        unset($userData['createdCategories']);
        unset($userData['categoriesOfInterest']);
        unset($userData['ownedFeeds']);
        unset($userData['createdFeeds']);
        unset($userData['roles']);
        unset($userData['news']);
        unset($userData['isEnabled']);
        unset($userData['lastLogin']);
        
        if (empty($userData['password'])) {
        	unset($userData['password']);
        }
        
        try {
        	$this->_db->beginTransaction();
        	
            $this->_user->update($userData, array('oid = ?' => $userData['oid']));
            $this->editProfile($profile);
            
            $this->_db->commit();
        } catch (Exception $e) {
        	$this->_db->rollBack();
        	
        	throw $e;
        }
	}

    /**
     * Edit user profile entry
     * 
     * @see application/models/Model_UserService#editProfile($user)
	 * @param Model_Entity_UserProfile $profile
	 * @return void
	 * @throws Exception
	 */
	public function editProfile(Model_Entity_UserProfile $profile) {
		$profileData = $profile->getOptions();
		
		$this->_profile->update($profileData, 
		                        array('oid = ?' => $profileData['oid']));
	}

	/**
     * Lock/Unlock user account
     * 
     * @param Model_Entity_User $user
     * @return void
	 * @see application/models/Model_UserService#setUserLock($user)
	 */
	public function setUserLock($user) {
		$lock['isEnabled'] = $user->getIsEnabled() ? 1 : 0;
		
		$this->_user->update($lock,
		                     array('oid = ?' => $user->getOid()));
	}
}